import {max, min} from "@sakitam-gis/kriging/src/utils.ts";
import {predict} from "@sakitam-gis/kriging/src";
import {pip} from "@sakitam-gis/kriging";
import {IDW} from "idw"

export function grid_(
    polygons: number[][][],
    variogram: {
        t: number[];
        n: number;
        model: (arg0: number, arg1: any, arg2: any, arg3: any, arg4: any) => void;
        x: number[];
        y: number[];
        nugget: any;
        range: any;
        sill: any;
        A: any;
        M: number[];
    },
    width: number,
    pipList: any
) {
    let i;
    let j;
    let k;
    const n = polygons.length;
    if (n === 0) return;

    // Boundaries of polygons space
    const {xlim, ylim, rangeList} = pipList

    // Alloc for O(n^2) space
    let xtarget;
    let ytarget;
    const a = Array(2);
    const b = Array(2);
    const x = Math.ceil((xlim[1] - xlim[0]) / width);
    const y = Math.ceil((ylim[1] - ylim[0]) / width);
    const A = Array(x + 1);
    for (i = 0; i <= x; i++) A[i] = Array(y + 1);
    for (i = 0; i < n; i++) {
        // Range for polygons[i]
        const {lxlim, lylim} = rangeList[i]

        // Loop through polygon subspace
        a[0] = Math.floor(((lxlim[0] - ((lxlim[0] - xlim[0]) % width)) - xlim[0]) / width);
        a[1] = Math.ceil(((lxlim[1] - ((lxlim[1] - xlim[1]) % width)) - xlim[0]) / width);
        b[0] = Math.floor(((lylim[0] - ((lylim[0] - ylim[0]) % width)) - ylim[0]) / width);
        b[1] = Math.ceil(((lylim[1] - ((lylim[1] - ylim[1]) % width)) - ylim[0]) / width);
        for (j = a[0]; j <= a[1]; j++) {
            for (k = b[0]; k <= b[1]; k++) {
                xtarget = xlim[0] + j * width;
                ytarget = ylim[0] + k * width;
                if (pip(polygons[i], xtarget, ytarget)) {
                    A[j][k] = predict(xtarget, ytarget, variogram);
                }
            }
        }
    }
    return {
        xlim,
        ylim,
        width,
        data: A,
        zlim: [min(variogram.t), max(variogram.t)],
    };
}

export function idw_grid(polygons: number[][][],
                         power: number,
                         width: number,
                         pipList: {
                             xlim: number[],
                             ylim: number[],
                             rangeList: { lxlim: number[], lylim: number[] }[]
                         },
                         idw: any) {
    let i;
    let j;
    let k;
    const n = polygons.length;
    if (n === 0) return;

    // Boundaries of polygons space
    const {xlim, ylim, rangeList} = pipList

    // Alloc for O(n^2) space
    let xtarget;
    let ytarget;
    const a = Array(2);
    const b = Array(2);
    const x = Math.ceil((xlim[1] - xlim[0]) / width);
    const y = Math.ceil((ylim[1] - ylim[0]) / width);
    const A = Array(x + 1);
    for (i = 0; i <= x; i++) A[i] = Array(y + 1);
    for (i = 0; i < n; i++) {
        // Range for polygons[i]
        const {lxlim, lylim} = rangeList[i]

        // Loop through polygon subspace
        a[0] = Math.floor(((lxlim[0] - ((lxlim[0] - xlim[0]) % width)) - xlim[0]) / width);
        a[1] = Math.ceil(((lxlim[1] - ((lxlim[1] - xlim[1]) % width)) - xlim[0]) / width);
        b[0] = Math.floor(((lylim[0] - ((lylim[0] - ylim[0]) % width)) - ylim[0]) / width);
        b[1] = Math.ceil(((lylim[1] - ((lylim[1] - ylim[1]) % width)) - ylim[0]) / width);
        for (j = a[0]; j <= a[1]; j++) {
            for (k = b[0]; k <= b[1]; k++) {
                xtarget = xlim[0] + j * width;
                ytarget = ylim[0] + k * width;
                if (pip(polygons[i], xtarget, ytarget)) {
                    A[j][k] = idw.evaluate([xtarget, ytarget], power);
                }
            }
        }
    }
    return {
        xlim,
        ylim,
        width,
        data: A,
    };
}

IDW.prototype.setExtent = function (extent: number[][]) {
    this.extent = extent
}
export {
    IDW
}